#include "UDPRecieve.h"
#include <qcoreapplication.h>
#include "src/common/log/log.h"
#include <QTimer>
#include <QDateTime>
#include <QDir>
#define  DogSN  "WLR0002"
#define TIMEOUT_SEC 6  // 设置超时时间为5秒
UDPReceive::UDPReceive(QObject *parent)
        : QObject{parent},m_port(9999),m_closeState(true),m_Path("")
{
    udpSocket = new QUdpSocket(this);
    m_connectionTimer = new QTimer(this);
    connect(m_connectionTimer, &QTimer::timeout, this, &UDPReceive::checkConnectionStatus);
    connect(m_connectionTimer, &QTimer::timeout, this, &UDPReceive::createDirectory);//定时创建目录
}

UDPReceive::~UDPReceive()
{
    udpSocket->close();
    delete udpSocket;
}
void UDPReceive::startReceiving(const QString &address, const quint16 &port){
    // 绑定UDP套接字到指定端口
    m_address = QHostAddress(address);
    m_port = port;
    udpSocket->bind();
    sendRequest();
    connect(udpSocket, &QUdpSocket::readyRead, this, &UDPReceive::processPendingDatagrams);  // 将readyRead信号连接到processPendingDatagrams槽函数
    //查看连接状态
    connect(udpSocket, &QUdpSocket::stateChanged, this, &UDPReceive::socketStateChanged);
    m_connectionTimer->start( TIMEOUT_SEC*1000);
}


void UDPReceive::processPendingDatagrams()
{
    static int timeOutCount = 0; // 超时统计连接

    while (true){
        //判断是否会超时
        if(!udpSocket->waitForReadyRead(TIMEOUT_SEC * 1000)){
            sendRequest();
            timeOutCount++;
            if(timeOutCount >= 10){
                LOG_ERROR("Recieved TimeOut And Close the Connection");
                timeOutCount= 0;
                udpSocket->close();
                m_closeState = false;
                break;
            }
        }
        if(udpSocket->hasPendingDatagrams()){
            sendRequest(); //每次发送aaaa
            QByteArray datagram;
            datagram.resize(udpSocket->pendingDatagramSize());
            // 读取待处理的数据报
            QHostAddress sender;
            quint16 senderPort;
            udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
            // 处理接收到的数据报
            std::string message = datagram.toStdString();

            if (message == "END") {
                continue;  // 接收到结束信号，停止接收图像数据
            }

            if (message.find("start") == 0) {
                // 提取图像大小并转换为整数
                int imgSize = std::stoi(message.substr(5));;
                // 接收图像数据并重构图像
                std::vector<uchar> imgData;
                bool completeFlag = true;

                // 如果接收到的图像大小有效，则继续接收图像数据
                if (imgSize > 0 && imgSize < 10*1024*1024) {  // 假设图像大小不会超过10MB
                    while (imgData.size() < imgSize) {
                        if (!udpSocket->waitForReadyRead(TIMEOUT_SEC * 1000)) {
                            LOG_ERROR("Receive timeout");
                            completeFlag = false;
                            break;  // 超时，停止接收图像数据
                        }

                        QByteArray packet;
                        packet.resize(udpSocket->pendingDatagramSize());
                        udpSocket->readDatagram(packet.data(), packet.size(), &sender, &senderPort);

                        std::string packetData = packet.toStdString();
                        if (packetData == "END") {
                            completeFlag = false;
                            break;  // 接收到结束信号，停止接收图像数据
                        }
                        imgData.insert(imgData.end(), packetData.begin(), packetData.end());
                    }
                } else {
                    LOG_ERROR("Invalid image size received");
                }
                if (completeFlag && !imgData.empty()) {
                    // 在单个独立的线程中显示图像
                    cv::Mat  image = decodeImage(imgData);
                    if(!image.empty())
                    {
                        saveImage(image);
                        emit sendDisplaySignal(image);
                    }else{
                        LOG_ERROR("Failed to decode image");
                    }
                }

            }
        }
    }
}
cv::Mat UDPReceive::decodeImage(std::vector<uchar> &data)
{
    cv::Mat image;
    if (data.size() > 0 && !data.empty()) {
        try {
            image = cv::imdecode(data, cv::IMREAD_COLOR);
            if(image.empty()){
                LOG_ERROR("Error decoding image empty iamge");
            }else if (image.rows <= 0 || image.cols <=0){
                LOG_ERROR("Error decoding imager Invalid iamge size");
                image.release();
            }
        } catch (const cv::Exception& ex) {
            LOG_ERROR("Error decoding image: " << ex.what());
        }
    }
    return image;
}
void UDPReceive::saveImage(const cv::Mat &image){
    //save image
    QImage qImage(image.data, image.cols, image.rows, static_cast<int>(image.step), QImage::Format_BGR888);
    QString fileName = m_Path + "/" + QString::number(QDateTime::currentDateTime().toMSecsSinceEpoch()) + ".jpg";
    bool success = qImage.save(fileName, "JPG");
    if(success){
        LOG_INFO("Save Image Success: " << fileName.toStdString().c_str());
    }else{
        LOG_ERROR("Save image failed!" );
    }
}

void UDPReceive::sendRequest(){
    QString reqMsg = "aaaa";
    if(udpSocket->writeDatagram(reqMsg.toUtf8(), m_address, m_port)== -1){
        LOG_ERROR("Sending Request Failed!");
        exit(EXIT_FAILURE);
    }
    return;
}

QString UDPReceive::getCurrentTime()
{
    QDateTime currentTime = QDateTime::currentDateTime();
    return currentTime.toString("yyyyMMddhhmmss");
}

void  UDPReceive::createDirectory()
{
    static int TimeCount = 0;
    if (TimeCount ==  0){
        QString directoryName = getCurrentTime();
        QString path = QDir::currentPath() + "/" +  DogSN +"/RGB"+ "/" + directoryName;
        QDir dir(path);
        // 判断数据是否存在
        if(!dir.exists()){
            if(dir.mkpath(".")){
                LOG_INFO("CreateDir Path Succesful path:" << path.toStdString());
                m_Path = path;
            }else{
                LOG_INFO("CreateDir Path Failed path:" << path.toStdString());
            }
        }
    }
    ++TimeCount;
    if(TimeCount >50)
    {
        TimeCount = 0; // 5分钟创建一次目录
    }
}

void UDPReceive::socketStateChanged(QAbstractSocket::SocketState state){
    if(state == QAbstractSocket::ConnectedState){
        m_conneted = true;
        LOG_INFO("  QAbstractSocket::ConnectedState");
    } else if (state == QAbstractSocket::ConnectingState){
        m_conneted= false;
        LOG_INFO("  QAbstractSocket::ConnectingState");
    }else if (state == QAbstractSocket::UnconnectedState){
        m_conneted= false;
        LOG_INFO(" QAbstractSocket::UnconnectedState");
    }else if (state == QAbstractSocket::ClosingState){
        LOG_INFO("QAbstractSocket::ClosingState");
    }
}

void  UDPReceive::checkConnectionStatus(){
    if(!m_conneted && m_closeState){
        LOG_INFO("Recieve TimeOut and Send Request again!"); //网络超时重新在传
        sendRequest();
    }else if (!m_conneted && !m_closeState){
        //关闭定时器
        m_connectionTimer->stop();
    }

}